package com.wangshouyu.mp.pay.common.utils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 王守钰
 * @description http工具类
 * @date 2020/8/13 11:37
 */
public class HttpUtils {

    private HttpUtils(){}

    /**
     * https
     */
    private static final String HTTPS = "https";

    /**
     * POST
     */
    private static final String POST = "POST";

    /**
     * GET
     */
    private static final String GET = "GET";

    /**
     * 连接超时
     */
    private static final Integer CONNECT_TIMEOUT = 3000;

    /**
     * 读取超时
     */
    private static final Integer READ_TIMEOUT = 3000;

    protected static TrustManager myX509TrustManager = new X509TrustManager() {

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }

    };

    /**
     * 创建连接
     * @param requestUrl 请求地址
     * @param method 请求方法
     * @return 返回结果
     * @throws Exception
     */
    private static HttpURLConnection connection(String requestUrl, String method) throws Exception {
        // 定义请求
        URL url = new URL(requestUrl);
        // 打开和URL之间的连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 设置请求类型
        connection.setRequestMethod(method);
        // 设置连接超时
        connection.setConnectTimeout(CONNECT_TIMEOUT);
        // 设置读取超时
        connection.setReadTimeout(READ_TIMEOUT);

        if(requestUrl.indexOf(HTTPS)==0){
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
            ((HttpsURLConnection) connection).setSSLSocketFactory(sslcontext.getSocketFactory());
        }
        if(POST.equalsIgnoreCase(method)){
            // 发送POST请求必须设置如下两行
            connection.setDoOutput(true);
            connection.setDoInput(true);
        }
        return connection;
    }


    /**
     * post xml数据
     * @param requestUrl 请求地址
     * @param xml 请求xml
     * @return 请求响应结果
     * @throws Exception
     */
    public static String postXml(String requestUrl, String xml) throws Exception{
        return postData(requestUrl, xml, new HashMap<>());
    }

    /**
     * post json数据
     * @param requestUrl 请求地址
     * @param json 请求json
     * @return 请求响应结果
     * @throws Exception
     */
    public static String postJson(String requestUrl, String json) throws Exception{
        Map<String, String> headers = new HashMap<>(2);
        headers.put("Accept-Charset", "UTF-8");
        headers.put("Content-Type", "application/json");
        return postData(requestUrl, json, headers);
    }

    /**
     * post数据
     * @param requestUrl 请求地址
     * @param data 请求数据
     * @param headers 请求头
     * @return 响应结果
     * @throws Exception
     */
    public static String postData(String requestUrl, String data, Map<String, String> headers) throws Exception{
        HttpURLConnection connection = null;
        BufferedReader in = null;
        OutputStreamWriter out = null;
        //定义返回结果
        StringBuffer result = new StringBuffer();
        try{
            connection = connection(requestUrl, POST);
            //循环遍历请求头
            for(String key : headers.keySet()){
                connection.setRequestProperty(key, headers.get(key));
            }
            // 建立实际的连接
            connection.connect();
            // 获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(connection.getOutputStream());
            out.write(data);
            out.flush();
            // 获取响应码
            int code = connection.getResponseCode();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }

            if(code < 200 || code >= 300){
                throw new RuntimeException("http response code:" + code + " errorMsg:" + result.toString());
            }
        }finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if(connection != null){
                connection.disconnect();
            }
        }
        return result.toString();
    }

    public static String postJson(String url, String json, String token) throws Exception {
        Map<String, String> headers = new HashMap<>(2);
        headers.put("Accept-Charset", "UTF-8");
        headers.put("Content-Type", "application/json");
        headers.put("Authorization", "WECHATPAY2-SHA256-RSA2048 " + token);
        return postData(url, json, headers);
    }

    /**
     * get请求
     * @param url 地址
     * @param token token
     * @return 响应结果
     * @throws Exception
     */
    public static String get(String url, String token) throws Exception {
        Map<String, String> headers = new HashMap<>(2);
        headers.put("Accept-Charset", "UTF-8");
//        headers.put("Content-Type", "application/json");
        headers.put("Authorization", "WECHATPAY2-SHA256-RSA2048 " + token);
        return getData(url, headers);
    }

    /**
     * 获取数据
     * @param url 地址
     * @param headers 头
     * @return 响应结果
     * @throws Exception
     */
    private static String getData(String url, Map<String, String> headers) throws Exception {
        HttpURLConnection connection = null;
        BufferedReader in = null;
        //定义返回结果
        StringBuffer result = new StringBuffer();
        try{
            connection = connection(url, GET);
            //循环遍历请求头
            for(String key : headers.keySet()){
                connection.setRequestProperty(key, headers.get(key));
            }
            // 建立实际的连接
            connection.connect();
            // 获取响应码
            int code = connection.getResponseCode();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            if(code < 200 || code >= 300){
                throw new RuntimeException("http response code:" + code + " errorMsg:" + result.toString());
            }
        }finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if(connection != null){
                connection.disconnect();
            }
        }
        return result.toString();
    }
}
